#
# Copyright 2008-2010 Vadim Zhukov <persgray@gmail.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
#    list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY AGAVA COMPANY ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL THE AGAVA COMPANY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and documentation are
# those of the authors and should not be interpreted as representing official
# policies, either expressed or implied, of the AGAVA Company.


#######################################
# Save backups on a one-per-week basis

package RB::RotateScheme::Weekly;
use strict;

use POSIX qw/mktime/;
use RB::RotateScheme;
use RB::Util;
our @ISA = qw/RB::RotateScheme/;


# We implement out own function instead of depending on Date::Calc
#  which doesn't exist in Perl distribution.
my %YearStartsFrom;
sub weekOfYear($$$) {
	my ($year, $month, $day) = @_;
	my $t = mktime(0, 0, 0, $day-1, $month-1, $year-1900);
	my @t2 = localtime $t;
	unless (exists $YearStartsFrom{$year}) {
		my $ty = mktime(0, 0, 0, 0, 0, $year-1900);
		my @ty2 = localtime $ty;
		# [6] - week day
		$YearStartsFrom{$year} = $ty2[6];
	}
	# [7] - day of year
	my $week = int(($t2[7] - $YearStartsFrom{$year}) / 7);
	# We do not need accurate result, just the same for every week
	return ($week, $year);
}

sub _makeKeepDecision($@) {
	my $this = shift;
	my $leftToFind = $this->{'_maxLeft'};
	my (@keep, %found, $date, $week, $year, $w, $lastW);
	foreach my $date (@_) {
		($week, $year) = weekOfYear(substr($date, 0, 4),
		    substr($date, 4, 2), substr($date, 6, 2) +
		    ${main::Config}->{'weekly_dump_at_wday'});
		$w = $year.$week;
		if ($leftToFind > 0 || $lastW eq $w) {
			unless (exists $found{$w}) {
				$leftToFind--;
			}
			$found{$w} = $date;
			$lastW = $w;
		}
	}
	return values %found;
}

my $LastRobin = 0;
sub _shouldUpdate($$$) {
	my ($this, $testDate, $hashSrc) = (shift, shift, shift);

	my ($testYear, $testMonth, $testMDay) = (substr($testDate, 0, 4),
	    substr($testDate, 4, 2)-1, substr($testDate, 6, 2));

	my $t = mktime(0, 0, 0, $testMDay, $testMonth, $testYear-1900);
	my @ta = localtime $t;
	my $testWDay = $ta[6];

	my $startWDay = 0;
	my $at = ${main::Config}->{'weekly_dump_at_wday'};
	if ($at) {
		if ($at eq 'hash') {
			$startWDay += chooseByHash(7, $hashSrc);
		} elsif ($at eq 'round-robin') {
			$startWDay += $LastRobin++;
			$LastRobin = 0 if $LastRobin == 7;
		} elsif ((my $dayNum = wdayByName($at)) != -1) {
			$startWDay += $dayNum;
		} else {
			# May be only a number, see RB::Profile
			$startWDay += $at;
		}
	}

	my $dd = ($testWDay - $startWDay);
	$dd += 7 if $dd < 0;
	my $startMDay = $testMDay - $dd;

	my ($start, $end);
	$start = formatAnyDate($testYear, $testMonth, $startMDay);
	$end = formatAnyDate($testYear, $testMonth, $startMDay + 7);

	return ($start, $end);
}


1;
